package mop.domain.task;

import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;

import mop.domain.project.Project;
import mop.domain.resource.Resource;
import mop.exception.IllegalDeadlineException;
import mop.exception.IllegalDependencyException;
import mop.exception.IllegalDescriptionException;
import mop.exception.IllegalStatusException;

/**
 * Class for Task.
 * 
 * @invar 	description is valid
 * 			|hasValidDescription()
 * 
 * @invar 	deadline is valid
 *  		|hasValidDeadline()
 *  
 * @invar 	dependencies are valid
 *  		|hasValidDependencies()
 * 
 * @author 	MOP Team 7
 */
public class Task implements Comparable<Task>
{
	
	/**
	 * Creates a task.
	 * 
	 * @param description	Description of the task
	 * @param start			Start date for the task
	 * @param deadline		Deadline for the task
	 * @param duration		Expected duration of the task
	 * @param res			List with resources the task uses
	 * @param dep			List with dependencies for this task
	 * 
	 * @effect Construct and set description
	 * 	|this(description)
	 * @effect Set resources
	 *  |setResources(res)
	 * @effect Set dependencies
	 *  |setDependencies(dep)
	 * @effect Set start date
	 *  |setStart(start)
	 * @effect Set expected duration
	 *  |setDuration(duration)
	 * @effect Set deadline
	 *  |setDeadline(deadline)
	 *  
	 * @post Task instance is created
	 *  
	 * @throws IllegalDescriptionException
	 *   if the description isn't a non-empty string
     *       |!isValidDescription(description)  
	 * @throws IllegalDeadlineException
	 *	if the deadline isn't a valid deadline according to business rule 1
	 * 		|!isValidDeadline(deadline,start,duration,dep)
	 */
	public Task(String description, Timestamp start, Timestamp deadline, Timestamp duration, 
			List<Resource> res, List<Task> dep) 
		throws IllegalDescriptionException, IllegalDeadlineException
	{
		this(description);
		
		if(dep == null)
			dep = new LinkedList<Task>();
		if(res == null)
			res = new LinkedList<Resource>();
		
		setResources(res);
		
		try{
			setDependencies(dep);
		}catch (IllegalDependencyException e) {
			//impossible on creation of Task, so just continue
		}
		
		setSchedule(start, deadline, duration);
	}
	
	/**
	 * Creates a task with only a description.
	 * 
	 * @param 	description
	 * 			Description of task.
	 * 
	 * @throws 	IllegalDescriptionException
	 * 			Description is invalid
	 * 			|!isValidDescription(description)
	 */
	public Task(String description) 
		throws IllegalDescriptionException
	{
		setDescription(description);
		setStatus(Status.UNFINISHED);
	}
	
	/**
	 * Creates a task without resources or dependencies.
	 * 
	 * @see Task(description, start, deadline, duration, res, dep)
	 */
	public Task(String description, Timestamp start, Timestamp deadline, Timestamp duration) 
		throws IllegalDeadlineException, IllegalDescriptionException 
	{
		this(description, start, deadline, duration, new LinkedList<Resource>(), new LinkedList<Task>());
	}
	
	/**
	 * Update task details.
	 * 
	 * Secured, so no attributes are changed if an error occurs.
	 * 
	 * @param description	New description of task
	 * @param start			Start date of task
	 * @param deadline		Deadline date of task
	 * @param duration		Duration date of task
	 * @param res			List of resources task uses
	 * @param dep			List of tasks task depends on
	 * 
	 * @effect Description gets changed to given value
	 * |setDescription(description)
	 * @effect schedule gets updated to given values
	 * |setSchedule(start,deadline,duration)
	 * @effect Task resources gets updated to given resources
	 * |setResources(res)
	 * @effect Task dependencies get updated to given tasks
	 * |setDependencies(dep)
	 * 
	 * @throws IllegalDeadlineException
	 *  Invalid deadline
	 *  |!isValidDeadline(start,duration,deadline)
	 * @throws IllegalDependencyException
	 *  Loop in dependency graph
	 *  |!isValidDependency(dep) 
	 * @throws IllegalDescriptionException
	 *  Illegal description
	 *  |!isValidDescription(description)
	 */
	public void updateDetails(String description, Timestamp start, Timestamp deadline, 
			Timestamp duration, List<Resource> res, List<Task> dep) 
		throws IllegalDeadlineException, IllegalDependencyException, IllegalDescriptionException
	{
		//Act like a sandbox
		//Backup old values in case we need to roll back
		String oldDescription = new String();
		oldDescription = this.getDescription() + "";
		Timestamp oldStart = new Timestamp(getStart().getTime());
		Timestamp oldDeadline = new Timestamp(getDeadline().getTime());
		Timestamp oldDuration = new Timestamp(getDuration().getTime());
		List<Resource> oldResources = new LinkedList<Resource>();
		List<Task> oldDependencies = new LinkedList<Task>();
		
		for(Resource r : getResources())
		{
			oldResources.add(r);
		}
		
		for(Task t : getDependencies())
		{
			oldDependencies.add(t);
		}
		
		try
		{
			setDescription(description);
			setDependencies(dep);
			setSchedule(start, deadline, duration);
			setResources(res);
		}
		catch(Throwable e)
		{
			//roll back
			setDescription(oldDescription);
			setDependencies(oldDependencies);
			setSchedule(oldStart, oldDeadline, oldDuration);
			setResources(oldResources);
	
			try {
				throw e;
			} catch (Throwable e1) {
				//If we throw an error we didn't declare, cannot happen
			}
		}
	}
	
	/***************************************************************************
	 * 							Task description
	 ***************************************************************************/
	
	/**
	 * Returns the description for this task
	 * 
	 * @return description;
	 */
	public String getDescription()
	{
		return this.description;
	}
	
	 /**
	  * Checks if the passed description is ok
	  * 
	  * @param description	The description you want checked
	  * 
	  * @return true if the passed description is not empty and its not null
	  *  |((!(description().equals("")) && description != null))
	  */
	 public static boolean isValidDescription(String description)
	 {
		 return ((!(description.trim().equals("")) && description != null));
	 }
	 
	 /**
	  * Checks whether description invariant is satisfied.
	  * 
	  * @return 
	  * 	true if task description is valid
	  * 	false if task description is invalid
	  *  |isValidDescription(getDescription())
	  */
	 public boolean hasValidDescription()
	 {
		 return isValidDescription(getDescription());
	 }
	
	 /**
	  * Sets the description.
	  * 
	  * @param description	The description for the task
	  *  
	  * @post Task description equals the given value
	  *  |getDescription() == description
	  *  
	  * @throws IllegalDescriptionException 
	  *       if the description isn't ok
	  *       |!isValidDescription(description)
	  *    
	  */
	 private void setDescription(String description) 
	 	throws IllegalDescriptionException
	 {

		 if(!isValidDescription(description))
		 {
			 throw new IllegalDescriptionException(description);
		 }
		 this.description = description;
	 }
	
	 /**
	  * variable for the description of the project
	  */
	private String description;
	
	
	/***************************************************************************
	 * 							Task Schedule
	 ***************************************************************************/
	
	/**
	 * Returns the start date for this project
	 * 
	 * @return start;
	 */
	private Timestamp getStart()
	{
		if(start == null)
			setStart(new Timestamp(0));
		
		return this.start;
	}
	
	 /**
	  * Set the start date
	  * 
	  * @param start	The start date for the task
	  *  
	  * @post Task start date equals the given one
	  *  |getStart() == start
	  */
	 private void setStart(Timestamp start)
	 {

		this.start = start;
	 }
	
	 /**
	  * Variable for the start date of the project
	  */
	private Timestamp start;
	
	
	/**
	 * Returns the expected duration for this project
	 * 
	 * @return duration;
	 */
	private Timestamp getDuration()
	{
		if(duration == null)
			setDuration(new Timestamp(0));
		
		return this.duration;
	}
	
	 /**
	  * Set the expected duration
	  * 
	  * @param duration	The expected duration for the task
	  *  
	  * @post Task duration equals given value
	  *  |getDuration() == dur
	  */
	 private void setDuration(Timestamp dur)
	 {
		 this.duration = dur;
	 }
	
	 /**
	  * Variable for the expected duration of the project
	  */
	private Timestamp duration;
	
	
	/**
	 * Returns the deadline for this project
	 * 
	 * @return deadline
	 */
	public Timestamp getDeadline()
	{
		return this.deadline;
	}
	
	 /**
	  * Checks if the passed deadline is ok
	  * 
	  * @param deadline	The deadline you want checked
	  * @param start	The start date
	  * @param duration	The expected duration
	  * 
	  * @return true if the passed deadline is valid according to business rule 1
	  */
	 public boolean isValidDeadline(Timestamp deadline, Timestamp start, 
			 Timestamp duration)
	 {
		
		Timestamp oldStart = new Timestamp(getStart().getTime());
		Timestamp oldDuration = new Timestamp(getDuration().getTime());
		
		setStart(start);
		setDuration(duration);
		
		if(deadline.getTime() < getEarliestEndTime().getTime())
		{
			setStart(oldStart);
			setDuration(oldDuration);
			return false;
		}
		
		for(Task p : getParents())
		{
			if(!p.hasValidDeadline())
			{
				setStart(oldStart);
				setDuration(oldDuration);
				return false;
			}
		}
		
		setStart(oldStart);
		setDuration(oldDuration);
	
		return true;
	 }
	 
	 /**
	  * Checks whether deadline invariant is satisfied
	  * 
	  * @return
	  *  true if deadline is valid
	  *  false if deadline is invalid
	  *   |isValidDeadline(getDeadline(),getStart(),getDuration(),getDependencies())
	  */
	 public boolean hasValidDeadline()
	 {
		 return isValidDeadline(getDeadline(),getStart(),getDuration());
	 }
	
	 /**
	  * Set the deadline
	  * 
	  * @param deadline	The deadline for the task
	  *  
	  * @post Task deadline equals the given value
	  *  |getDeadline() == deadline
	  *    
	  */
	 private void setDeadline(Timestamp deadline)
	 {
		 this.deadline = deadline;
	 }
	
	 /**
	  * variable for the deadline of the project
	  */
	private Timestamp deadline;
	
	/**
	 * Returns earliest possible endTime
	 * 
	 * @return Earliest possible endtime
	 * 	|getEarliestEndTime(getStart(),getDuration(),getDependencies());
	 */
	private Timestamp getEarliestEndTime()
	{
		return getEarliestEndTime(getStart(),getDuration(),getDependencies());
	}
	
	/**
	 * Returns earliest possible endTime
	 * 
	 * @return Earliest possible end time calculated as: latest(start,earliestEndTime(dependencies)) + duration
	 */
	private static Timestamp getEarliestEndTime(Timestamp start, Timestamp duration, 
			List<Task> dep)
	{
		long time = 0;
		
		for(Task t : dep)
		{
			if(t.getEarliestEndTime().getTime() > time)
				time = t.getEarliestEndTime().getTime();
		}
		
		time = Math.max(time,start.getTime()) + duration.getTime();
		
		return new Timestamp(time);
	}
	
	/**
	 * Sets the start, deadline and duration
	 * 
	 * @param start		Start date of task
	 * @param deadline	Deadline date of task
	 * @param duration	Duration of task
	 * 
  	 * @throws IllegalDeadlineException 
	 *    if the deadline is not valid
	 *       |!isValidDeadline(deadline,start,duration,getDependencies())
	 */
	private void setSchedule(Timestamp start, Timestamp deadline, Timestamp duration) throws IllegalDeadlineException
	 {

		 if(!isValidDeadline(deadline,start,duration))
		 {
			 throw new IllegalDeadlineException(getEarliestEndTime());
		 }
		 setStart(start);
		 setDuration(duration);
		 setDeadline(deadline);
	 }
	
	/**
	 * Returns list with start date, duration and deadline of task
	 * 
	 * @return	List with timestamps of date, duration and deadline
	 */
	public List<Timestamp> getSchedule()
	{
		List<Timestamp> list = new LinkedList<Timestamp>();
		list.add(getStart());
		list.add(getDeadline());
		list.add(getDuration());
		return list;
	}
	
	/**
	 * Compare to other task
	 * Compares on deadline
	 * 
	 * @param o
	 * 	Task to compare with
	 * 
	 * @return
	 *  -1 if deadline of given task is after deadline of this task
	 *  0 if equal
	 *  1 if deadline of given task is before deadline of this task
	 */
	public int compareTo(Task o) {
		return this.getDeadline().compareTo(o.getDeadline());
	}
	
	/***************************************************************************
	 * 							Task dependencies
	 ***************************************************************************/
	
	/**
	 * Return list with dependencies
	 * 
	 * @return dependencies
	 */
	public List<Task> getDependencies()
	{
		if(dependencies == null)
			dependencies = new LinkedList<Task>();
		
		return dependencies;
	}
	
	/**
	 * Set the dependencies to given list
	 * 
	 * @effect removes deleted dependencies
	 * 	|removeDepencies(dep)
	 * @effect add new dependencies
	 * 	|addDependencies(dep)
	 * 
	 * @throws IllegalDependencyException
	 * 	If dependencies are not valid
	 * 		|!isValidDependencies(this,dep)
	 */
	public void setDependencies(List<Task> dep) 
	throws IllegalDependencyException
	{
		if(!isValidDependencies(this,dep))
			throw new IllegalDependencyException();
		removeDependencies(dep);
		/** bugfix seba this shit aint working */

		addDependencies(dep);
	}
	
	/**
	* Checks whether dependencies invariant (no loops) is satisfied
	* 
	* @return
	*  true if dependencies are valid (no loop)
	*  false if dependencies are invalid
	*   |isValidDependencies(this,getDependencies())
	*/
	public boolean hasValidDependencies()
	{
		return isValidDependencies(this,getDependencies());
	}
	
	/**
	 * Check whether given task can use given task list as dependencies without creating a loop
	 * this is the reverse of dependsOn
	 * 
	 * @see dependsOn(t,dep)
	 * 
	 * @return 
	 * 	false if this configuration would create a loop
	 * 	true otherwise
	 */
	public static boolean isValidDependencies(Task t, List<Task> dep)
	{
		if(dependsOn(t,dep))
			return false;
		return true;
	}
	
	/**
	 * Checks whether given task is a direct or in-direct dependency of this task
	 * 
	 * @see dependsOn(t,getDependencies())
	 */
	private boolean dependsOn(Task t)
	{
		return dependsOn(t,getDependencies());
	}
	
	/**
	 * Checks whether a given task belongs to a given dependency list
	 * 
	 * @param t		The task to check
	 * @param dep	The dependency list
	 * 
	 * @return 
	 * 	true if task direct or indirect belongs to dep
	 * 	false otherwise
	 */
	private static boolean dependsOn(Task t, List<Task> dep)
	{
		for(Task d : dep)
		{
			if(d.equals(t) || d.dependsOn(t))
			{
				return true;
			}
		}
		return false;
	}
	
	
	
	/**
	 * Removes the current dependencies that are not in the given list
	 * 
	 * @param dep 	List with new dependencies
	 * 
	 * @post All task dependencies are in the given dep list
	 * 	|for i = 0 ... getDependencies().size() - 1
	 * 	|	dep.contains(getDependencies().get(i)) == true
	 */
	synchronized private void removeDependencies(List<Task> dep)
	{
		for(Task t : getDependencies())
		{
			if(!dep.contains(t))
			{
				t.removeParent(this);
			}
		}
<<<<<<< .mine
		this.dependencies = new LinkedList<Task>(); // heck to avoid problems
=======
		
		this.dependencies = new LinkedList<Task>(); // hack to avoid problems
>>>>>>> .r88
	}
	
	/**
	 * Removes given dependency and updates given task
	 * 
	 * @param t	The dependency to be removed from the task dependencies
	 * 
	 * @effect remove this task from the given task (t) 'dependsonme' list to maintain integrity
	 * 	|t.removeDependsOnMe(this)
	 * @effect remove t from dependencies
	 * 	|getDependencies().remove(t)
	 */
	synchronized private void removeDependency(Task t)
	{
		t.removeParent(this);
		getDependencies().remove(t);
	}
	
	/**
	 * Adds dependencies from given list that are not dependencies of this task yet
	 * 
	 * @param dep 	List with new dependencies
	 * 
	 * @post All dependencies from given dep list are in the task dependencies list
	 * 	|for i = 0 ... dep.size() - 1
	 * 	|	getDependencies().contains(dep.get(i)) == true
	 */
	synchronized  private void addDependencies(List<Task> dep)
	{
		for(Task t : dep)
		{
			if(!getDependencies().contains(t))
			{
				addDependency(t);
			}
		}
	}
	
	/**
	 * Adds given dependency and updates given task
	 * 
	 * @param t	The dependency to be added to the task dependencies
	 * 
	 * @effect add this task to the 'dependsonme' list of t to maintain integrity
	 * 	|t.addDependsOnMe(this)
	 * @effect add t to the dependencies list
	 * 	|getDependencies().add(t)
	 */
	private void addDependency(Task t)
	{
		t.addParent(this);
		this.getDependencies().add(t);
	}

	/**
	 * List containing task dependencies
	 */
	private List<Task> dependencies;
	
	/**
	 * Return list with task that directly depend on this task
	 * 
	 * @return parents
	 */
	public List<Task> getParents()
	{
		if(parents == null)
			parents = new LinkedList<Task>();
		return parents;
	}
	
	/**
	 * Add task that depends on this task
	 * 
	 * @param t	Task to add
	 * 
	 * @effect add task that depends on this task
	 * 	|getParents().add(t);
	 */
	private void addParent(Task t)
	{
		this.getParents().add(t);
	}
	
	/**
	 * Remove task that depends on this task
	 * 
	 * @param t	Task to remove
	 * 
	 * @effect removes task that depends on this task
	 * 	|getParents().remove(t);
	 * @effect remove this from the dependency list of the parent
	 * | parent.remoceDependency(t)
	 */
	private void removeParent(Task t)
	{
		//t.removeDependency(this);
		this.getParents().remove(t);
	}
	
	/**
	 * Get a list with all tasks that depend directly or indirectly on this task
	 * @return List with all direct and indirect parents
	 */
	public List<Task> getAllParents()
	{
		List<Task> list = new LinkedList<Task>();
		getAllParents(list);
		return list;
	}
	
	/**
	 * Add all tasks that depend directly or indirectly on this task to given list
	 * @param list	List to add parents to
	 */
	private void getAllParents(List<Task> list)
	{
		for(Task p : getParents())
		{
			list.add(p);
			p.getAllParents(list);
		}
		//return list;
	}
	
	/**
	 * List contain tasks that depend on this task (have this task as dependency)
	 */
	private List<Task> parents;
	
	/***************************************************************************
	 * 							Task resources
	 ***************************************************************************/
	
	/**
	 * Return list with resources
	 * 
	 * @return resources
	 */
	public List<Resource> getResources()
	{
		if(resources == null)
			resources = new LinkedList<Resource>();
		
		return resources;
	}
	
	
	/**
	 * Set the resources to given list
	 * 
	 * @effect removes deleted resources
	 * 	|removeResources(res);
	 * @effect add new resources
	 * 	|addResources(res);
	 */
	public void setResources(List<Resource> res)
	{
		removeResources(res);
		addResources(res);
	}
	
	/**
	 * Removes the current resources that are not in the given list
	 * 
	 * @param res	List with new resources
	 * 
	 * @post All task resources are in the given res list
	 * 	|for i = 0 ... getResources().size() - 1
	 * 	|	res.contains(getResources().get(i)) == true
	 */
	private void removeResources(List<Resource> res)
	{
		for(Resource r : getResources())
		{
			if(!res.contains(r))
			{
				removeResource(r);
			}
		}
	}
	
	/**
	 * Removes given resource and updates given resource with task
	 * 
	 * @param t	The resource to be removed from the task resources list
	 * 
	 * @effect remove this task from the given resource 'tasksRequiring' list to maintain integrity
	 * 	|getTasksRequiring().remove(this)
	 * @effect remove r from resources
	 * 	|getResources().remove(r)
	 */
	private void removeResource(Resource r)
	{
		r.getTasksRequiring().remove(this);
		getResources().remove(r);
	}
	
	/**
	 * Adds resources from given list that are not resources of this task yet
	 * 
	 * @param dep 	List with new resources
	 * 
	 * @post All resources from given res list are in the task resources list
	 * 	|for i = 0 ... res.size() - 1
	 * 	|	getResources().contains(res.get(i)) == true
	 */
	private void addResources(List<Resource> res)
	{
		for(Resource r : res)
		{
			if(!getResources().contains(r))
			{
				addResource(r);
			}
		}
	}
	
	/**
	 * Adds given resource and updates given resource with task
	 * 
	 * @param r	The resource to be added to the task resources
	 * 
	 * @effect Add this task to the given resource 'tasksRequiring' list to maintain integrity
	 * 	|r.getTasksRequiring().add(this)
	 * 
	 * @effect Add r to resources
	 * 	|getResources().add(r);
	 */
	private void addResource(Resource r)
	{
		r.getTasksRequiring().add(this);
		this.getResources().add(r);
	}

	
	/**
	 * List containing task resources
	 */
	private List<Resource> resources;
	
	/***************************************************************************
	 * 							Task status
	 ***************************************************************************/
	
	/**
	 * Sets the status
	 * 
	 * @param status	New description of the status value
	 *  
	 * @note	Accepts only: unfinished, success, failed
	 * 
	 * @post Status is set
	 * 	|getStatus() == satusDescription
	 * 
	 * @throws IllegalStatusException
	 *  If status is illegal (Status.AVAILABLE or Status.UNAVAILABLE or non existing status)
	 */
	public void setStatus(String statusDescription)
	throws IllegalStatusException
	{
		Status status = stringToStatus(statusDescription);
		
		switch(status)
		{
			case AVAILABLE:
			case UNAVAILABLE:
				throw new IllegalStatusException(statusDescription);
		}
		
		this.status = status;
	}
	
	/**
	 * Sets the status
	 * 
	 * @param status	New status
	 * 
	 * @post Status is set
	 * 	|this.status == status
	 * 
	 */
	private void setStatus(Status status)
	{
		this.status = status;
	}
	
	/**
	 * Returns status that matches string
	 * 
	 * @param status	Description of status
	 * 
	 * @return Status enum type
	 * 
	 * @throws IllegalStatusException
	 * 	If there doesn't exist a matching status
	 */
	private Status stringToStatus(String status) 
	throws IllegalStatusException
	{
		if(status.equals("Unfinished"))
			return Status.UNFINISHED;
		
		if(status.equals("Failed"))
			return Status.FAILED;
		
		if(status.equals("Successful"))
			return Status.SUCCESSFUL;
		
		if(status.equals("Available"))
			return Status.AVAILABLE;
		
		if(status.equals("Unavailable"))
			return Status.UNAVAILABLE;
		
		throw new IllegalStatusException(status);
	}
	
	/**
	 * Return the status of the task
	 * Doesn't differentiate between available and unavailable
	 * 
	 * @return status
	 */
	public String getStatus()
	{
		return status.getDescription();
	}
	
	/**
	 * Returns the extended status
	 * The extended status differentiates between available and unavailable when the task is not yet finished
	 *
	 * @return
	 *  Status available if task is available
	 *   |available
	 *  Status unavailable if task is unavailable because of an unfinished dependency or an unavailable resource
	 *   |unavailable
	 *  Normal status if task is finished
	 *  	|getStatus()
	 */
	public String getExtendedStatus()
	{
		if(!dependenciesFinished() || !resourcesAvailable())
			return Status.UNAVAILABLE.getDescription();
		
		if(status.equals(Status.UNFINISHED))
			return Status.AVAILABLE.getDescription();
		
		return getStatus();
	}
	
	/**
	 * Checks whether all resources are available
	 * 
	 * @return
	 * 	true if all are available
	 * 	false otherwise
	 */
	private boolean resourcesAvailable()
	{
		for(Resource r : getResources())
		{
			if(!r.isAvailable())
				return false;
		}
		return true;
	}
	
	/**
	 * Checks if the dependencies are finished or not
	 * 
	 * @return
	 * 	true if all dependencies are finished
	 *  false if not all dependencies are finished
	 */
	private boolean dependenciesFinished()
	{
		for(Task t : getDependencies())
		{
			if(t.getStatus().equals(Status.UNFINISHED.getDescription()))
				return false;
			if(!t.dependenciesFinished())
				return false;
		}
		
		return true;
	}
	
	/**
	 * Attribute representing the status of the task
	 */
	private Status status;
	
	/***************************************************************************
	 * 							Task project
	 ***************************************************************************/
	
	/**
	 * Sets the project to given value
	 * 
	 * @param p Project
	 * 
	 * @post project equals given value
	 * 	|getProject() == p
	 */
	public void setProject(Project p)
	{
		this.project = p;
	}
	
	/**
	 * Return project to which the task belongs
	 * 
	 * @return project
	 */
	public Project getProject()
	{
		return project;
	}
	
	/**
	 * Variable to indicate to which project the task belongs
	 */
	private Project project = null;

	/***************************************************************************
	 * 							Terminate task
	 ***************************************************************************/
	

	/**
	 * Terminate this item.
	 * 
     * @effect Terminate without terminating parents
     * 	|terminate(false)     
	 */
	public void terminate(){
		terminate(false);
	}
	
	/**
	 * Terminate this item.
	 * 
     * @post This item is terminated.
     *	| new.isTerminated()   
	 */
	public void terminate(boolean terminateParents)
	{	
		// copy parents list to avoid concurrent modification exception on linkedlist
		List<Task> list = new LinkedList<Task>();
		list.addAll(getParents());
		for(Task p : list)
		{
			if(terminateParents)
				p.terminate(true);
			p.removeDependency(this);
		}
		
	}
}
